<template>
  <view :style="'position: relative;' + customStyle + ';' + painterStyle">
    <canvas :style="photoStyle + ';position: absolute; left: -9999px; top: -9999rpx;'" canvasId="photo"></canvas>
    <canvas :style="painterStyle + ';position: absolute;'" canvasId="bottom"></canvas>
    <canvas :style="painterStyle + ';position: absolute;'" canvasId="k-canvas"></canvas>
    <canvas :style="painterStyle + ';position: absolute;'" canvasId="top"></canvas>
    <canvas
        :disableScroll="true"
        :style="painterStyle + ';position: absolute;'"
        canvasId="front"
        @touchcancel="onTouchCancel"
        @touchend="onTouchEnd"
        @touchmove="onTouchMove"
        @touchstart="onTouchStart"
    ></canvas>
  </view>
</template>

<script>
var t = require('../../../@babel/runtime/helpers/interopRequireDefault').default;
var e = require('../../../@babel/runtime/helpers/createForOfIteratorHelper');
var i = require('../../../@babel/runtime/helpers/toConsumableArray');
var s = t(require('./lib/pen'));
var n = require('./lib/downloader');
var o = require('./lib/util');
var r = new n.default();

function c(t, e) {
  String.prototype.toPx = function (i, s) {
    if ('0' === this) {
      return 0;
    }
    var n = (i ? /^-?[0-9]+([.]{1}[0-9]+){0,1}(rpx|px|%)$/g : /^[0-9]+([.]{1}[0-9]+){0,1}(rpx|px|%)$/g).exec(this);
    if (!this || !n) {
      console.error('The size: '.concat(this, ' is illegal'));
      return 0;
    }
    var o = n[2];
    var r = parseFloat(this);
    var c = 0;
    'rpx' === o ? (c = Math.round(r * (t || 0.5) * (e || 1))) : 'px' === o ? (c = Math.round(r * (e || 1))) : '%' === o && (c = Math.round((r * s) / 100));
    return c;
  };
}

export default {
  data() {
    return {
      picURL: '',
      showCanvas: true,
      painterStyle: '',
      photoStyle: '',
      hasMove: false,
      canvasWidthInPx: 0,
      canvasHeightInPx: 0,
      paintCount: 0,
      currentPalette: {},
      movingCache: {},
      outterDisabled: false,
      isDisabled: false,
      needClear: false,
      startX: 0,
      startY: 0,
      startH: 0,
      startW: 0,
      isScale: false,
      startTimeStamp: 0,
      touchedView: {},
      findedIndex: -1,
    };
  },

  props: {
    customStyle: {
      type: String
    },
    customActionStyle: {
      type: Object
    },
    palette: {
      type: Object
    },
    dancePalette: {
      type: Object
    },
    scaleRatio: {
      type: Number,
      default: 1
    },
    widthPixels: {
      type: Number,
      default: 0
    },
    dirty: {
      type: Boolean,
      default: false
    },
    LRU: {
      type: Boolean,
      default: true
    },
    action: {
      type: Object
    },
    disableAction: {
      type: Boolean
    },
    clearActionBox: {
      type: Boolean
    }
  },
  methods: {
    isEmpty: function (t) {
      for (var e in t) {
        return false;
      }
      return true;
    },
    isNeedRefresh: function (t, e) {
      return !(!t || this.isEmpty(t) || (this.dirty && o.equal(t, e)));
    },
    getBox: function (t, e) {
      var i = {
        type: 'rect',
        css: {
          height: ''.concat(t.bottom - t.top, 'px'),
          width: ''.concat(t.right - t.left, 'px'),
          left: ''.concat(t.left, 'px'),
          top: ''.concat(t.top, 'px'),
          borderWidth: '4rpx',
          borderColor: '#1A7AF8',
          color: 'transparent'
        }
      };
      if ('text' === e) {
        i.css = Object.assign({}, i.css, {
          borderStyle: 'dashed'
        });
      }
      if (this.customActionStyle && this.customActionStyle.border) {
        i.css = Object.assign({}, i.css, this.customActionStyle.border);
      }
      Object.assign(i, {
        id: 'box'
      });
      return i;
    },
    getScaleIcon: function (t, e) {
      var i = {};
      var s = this.customActionStyle;
      (i =
          s && s.scale
              ? {
                type: 'image',
                url: 'text' === e ? s.scale.textIcon : s.scale.imageIcon,
                css: {
                  height: ''.concat(48, 'rpx'),
                  width: ''.concat(48, 'rpx'),
                  borderRadius: ''.concat(24, 'rpx')
                }
              }
              : {
                type: 'rect',
                css: {
                  height: ''.concat(48, 'rpx'),
                  width: ''.concat(48, 'rpx'),
                  borderRadius: ''.concat(24, 'rpx'),
                  color: '#0000ff'
                }
              }).css = Object.assign({}, i.css, {
        align: 'center',
        left: ''.concat(t.right + '2rpx'.toPx(), 'px'),
        top: ''.concat('text' === e ? t.top - '2rpx'.toPx() - i.css.height.toPx() / 2 : t.bottom - '2rpx'.toPx() - i.css.height.toPx() / 2, 'px')
      });
      Object.assign(i, {
        id: 'scale'
      });
      return i;
    },
    getDeleteIcon: function (t) {
      var e = {};
      var i = this.customActionStyle;
      (e =
          i && i.scale
              ? {
                type: 'image',
                url: i.delete.icon,
                css: {
                  height: ''.concat(48, 'rpx'),
                  width: ''.concat(48, 'rpx'),
                  borderRadius: ''.concat(24, 'rpx')
                }
              }
              : {
                type: 'rect',
                css: {
                  height: ''.concat(48, 'rpx'),
                  width: ''.concat(48, 'rpx'),
                  borderRadius: ''.concat(24, 'rpx'),
                  color: '#0000ff'
                }
              }).css = Object.assign({}, e.css, {
        align: 'center',
        left: ''.concat(t.left - '2rpx'.toPx(), 'px'),
        top: ''.concat(t.top - '2rpx'.toPx() - e.css.height.toPx() / 2, 'px')
      });
      Object.assign(e, {
        id: 'delete'
      });
      return e;
    },
    doAction: function (t, e, s, n) {
      var that = this;
      var c = null;
      if (t) {
        c = t.view;
      }
      if (c && c.id && this.touchedView.id !== c.id) {
        for (var a = this.currentPalette.views, h = 0; h < a.length; h++) {
          if (a[h].id === c.id) {
            this.touchedView = a[h];
            this.findedIndex = h;
            this.sliceLayers();
            break;
          }
        }
      }
      var d = this.touchedView;
      if (d && !this.isEmpty(d)) {
        if (c && c.css) {
          n
              ? (d.css = c.css)
              : Array.isArray(d.css) && Array.isArray(c.css)
                  ? (d.css = Object.assign.apply(Object, [{}].concat(i(d.css), i(c.css))))
                  : Array.isArray(d.css)
                      ? (d.css = Object.assign.apply(Object, [{}].concat(i(d.css), [c.css])))
                      : Array.isArray(c.css)
                          ? (d.css = Object.assign.apply(Object, [{}, d.css].concat(i(c.css))))
                          : (d.css = Object.assign({}, d.css, c.css));
        }
        if (c && c.rect) {
          d.rect = c.rect;
        }
        c && c.url && d.url && c.url !== d.url
            ? r
                .download(c.url, this.LRU)
                .then(function (t) {
                  if (c.url.startsWith('https')) {
                    d.originUrl = c.url;
                  }
                  d.url = t;
                  uni.getImageInfo({
                    src: t,
                    success: function (t) {
                      d.sHeight = t.height;
                      d.sWidth = t.width;
                      that.reDraw(d, e, s);
                    },
                    fail: function () {
                      that.reDraw(d, e, s);
                    }
                  });
                })
                .catch(function (t) {
                  console.error(t);
                  that.reDraw(d, e, s);
                })
            : (c && c.text && d.text && c.text !== d.text && (d.text = c.text),
            c && c.content && d.content && c.content !== d.content && (d.content = c.content),
                this.reDraw(d, e, s));
      }
    },
    reDraw: function (t, e, i) {
      var that = this;
      var o = {
        width: this.currentPalette.width,
        height: this.currentPalette.height,
        views: this.isEmpty(t) ? [] : [t]
      };
      var r = new s.default(this.globalContext, o);
      i && 'text' === t.type
          ? r.paint(
              function (t) {
                if (e) {
                  e(t);
                }
                that.$emit('viewUpdate', {
                  detail: {
                    view: that.touchedView
                  }
                });
              },
              true,
              this.movingCache
          )
          : (i || this.isScale || r.paint(),
              r.paint(function (t) {
                if (e) {
                  e(t);
                }
                that.$emit('viewUpdate', {
                  detail: {
                    view: that.touchedView
                  }
                });
              }));
      var c = t.rect;
      var a = t.css;
      var h = t.type;
      this.block = {
        width: this.currentPalette.width,
        height: this.currentPalette.height,
        views: this.isEmpty(t) ? [] : [this.getBox(c, t.type)]
      };
      if (a && a.scalable) {
        this.block.views.push(this.getScaleIcon(c, h));
      }
      if (a && a.deletable) {
        this.block.views.push(this.getDeleteIcon(c));
      }
      new s.default(this.frontContext, this.block).paint();
    },
    isInView: function (t, e, i) {
      return t > i.left && e > i.top && t < i.right && e < i.bottom;
    },
    isInDelete: function (t, i) {
      var s;
      var n = e(this.block.views);
      try {
        for (n.s(); !(s = n.n()).done;) {
          var o = s.value;
          if ('delete' === o.id) {
            return t > o.rect.left && i > o.rect.top && t < o.rect.right && i < o.rect.bottom;
          }
        }
      } catch (t) {
        n.e(t);
      } finally {
        n.f();
      }
      return false;
    },
    isInScale: function (t, i) {
      var s;
      var n = e(this.block.views);
      try {
        for (n.s(); !(s = n.n()).done;) {
          var o = s.value;
          if ('scale' === o.id) {
            return t > o.rect.left && i > o.rect.top && t < o.rect.right && i < o.rect.bottom;
          }
        }
      } catch (t) {
        console.log('CatchClause', t);
        n.e(t);
      } finally {
        n.f();
      }
      return false;
    },

    onClick: function () {
      for (var t = this.startX, e = this.startY, i = [], s = false, n = -1, o = this.currentPalette.views.length - 1; o >= 0; o--) {
        var r = this.currentPalette.views[o];
        var c = r.rect;
        if (this.touchedView && this.touchedView.id && this.touchedView.id === r.id && this.isInDelete(t, e, c)) {
          i.length = 0;
          n = o;
          s = true;
          break;
        }
        if (this.isInView(t, e, c)) {
          i.push({
            view: r,
            index: o
          });
        }
      }
      this.touchedView = {};
      if (0 === i.length) {
        this.findedIndex = -1;
      } else {
        var a = 0;
        var h = i.filter(function (t) {
          return Boolean(t.view.id);
        });
        if (0 === h.length) {
          this.findedIndex = i[0].index;
        } else {
          for (a = 0; a < h.length; a++) {
            if (this.findedIndex === h[a].index) {
              a++;
              break;
            }
          }
          if (a === h.length) {
            a = 0;
          }
          this.touchedView = h[a].view;
          this.findedIndex = h[a].index;
          this.$emit('viewClicked', {
            detail: {
              view: this.touchedView
            }
          });
        }
      }
      this.findedIndex < 0 || (this.touchedView && !this.touchedView.id)
          ? (this.frontContext.draw(),
              s
                  ? (this.$emit('touchEnd', {
                    detail: {
                      view: this.currentPalette.views[n],
                      index: n,
                      type: 'delete'
                    }
                  }),
                      this.doAction())
                  : this.findedIndex < 0 &&
                  this.$emit('viewClicked', {
                    detail: {}
                  }),
              (this.findedIndex = -1),
              (this.prevFindedIndex = -1))
          : this.touchedView && this.touchedView.id && this.sliceLayers();
    },
    sliceLayers: function () {
      var that = this;
      var e = this.currentPalette.views.slice(0, this.findedIndex);
      var i = this.currentPalette.views.slice(this.findedIndex + 1);
      var n = {
        width: this.currentPalette.width,
        height: this.currentPalette.height,
        background: this.currentPalette.background,
        views: e
      };
      var o = {
        width: this.currentPalette.width,
        height: this.currentPalette.height,
        views: i
      };
      this.prevFindedIndex < this.findedIndex
          ? (new s.default(this.bottomContext, n).paint(),
              this.doAction(null, function (e) {
                that.movingCache = e;
              }),
              new s.default(this.topContext, o).paint())
          : (new s.default(this.topContext, o).paint(),
              this.doAction(null, function (e) {
                that.movingCache = e;
              }),
              new s.default(this.bottomContext, n).paint());
      this.prevFindedIndex = this.findedIndex;
    },

    onTouchStart: function (t) {
      if (!this.isDisabled) {
        var e = t.touches[0];
        var i = e.x;
        var s = e.y;
        this.startX = i;
        this.startY = s;
        this.startTimeStamp = new Date().getTime();
        if (this.touchedView && !this.isEmpty(this.touchedView)) {
          var n = this.touchedView.rect;
          this.isInScale(i, s, n)
              ? ((this.isScale = true), (this.movingCache = {}), (this.startH = n.bottom - n.top), (this.startW = n.right - n.left))
              : (this.isScale = false);
        } else {
          this.isScale = false;
        }
      }
    },
    onTouchEnd: function (t) {
      this.isDisabled ||
      (new Date().getTime() - this.startTimeStamp <= 500 && !this.hasMove
          ? !this.isScale && this.onClick(t)
          : this.touchedView &&
          !this.isEmpty(this.touchedView) &&
          this.$emit('touchEnd', {
            detail: {
              view: this.touchedView
            }
          }),
          (this.hasMove = false));
    },
    onTouchCancel: function (t) {
      this.isDisabled || this.onTouchEnd(t);
    },
    onTouchMove: function (t) {
      var that = this;
      if (!this.isDisabled && ((this.hasMove = true), this.touchedView && (!this.touchedView || this.touchedView.id))) {
        var i = t.touches[0];
        var s = i.x;
        var n = i.y;
        var o = s - this.startX;
        var r = n - this.startY;
        var c = this.touchedView;
        var a = c.rect;
        var h = c.type;
        var d = {};
        if (this.isScale) {
          var l = this.startW + o > 1 ? this.startW + o : 1;
          if (this.touchedView.css && this.touchedView.css.minWidth && l < this.touchedView.css.minWidth.toPx()) {
            return;
          }
          if (this.touchedView.rect && this.touchedView.rect.minWidth && l < this.touchedView.rect.minWidth) {
            return;
          }
          var u = this.startH + r > 1 ? this.startH + r : 1;
          d = {
            width: ''.concat(l, 'px')
          };
          if ('text' !== h) {
            d.height = ''.concat('image' === h ? (l * this.startH) / this.startW : u, 'px');
          }
        } else {
          this.startX = s;
          this.startY = n;
          d = {
            left: ''.concat(a.x + o, 'px'),
            top: ''.concat(a.y + r, 'px'),
            right: void 0,
            bottom: void 0
          };
        }
        this.doAction(
            {
              view: {
                css: d
              }
            },
            function (t) {
              if (that.isScale) {
                that.movingCache = t;
              }
            },
            !this.isScale
        );
      }
    },
    initScreenK: function () {
      if (!(getApp() && getApp().globalData.systemInfo && getApp().globalData.systemInfo.screenWidth)) {
        try {
          getApp().globalData.systemInfo = uni.getSystemInfoSync();
        } catch (t) {
          console.log('CatchClause', t);
          console.log('CatchClause', t);
          return void console.error('Painter get system info failed, '.concat(JSON.stringify(t)));
        }
      }
      this.screenK = 0.5;
      if (getApp() && getApp().globalData.systemInfo && getApp().globalData.systemInfo.screenWidth) {
        this.screenK = getApp().globalData.systemInfo.screenWidth / 750;
      }
      c(this.screenK, this.scaleRatio);
    },
    initDancePalette: function () {
      var that = this;
      this.isDisabled = true;
      this.initScreenK();
      this.downloadImages(this.dancePalette).then(function (e) {
        that.currentPalette = e;
        var i = e.width;
        var n = e.height;
        i && n
            ? (that.setData({
              painterStyle: 'width:'.concat(i.toPx(), 'px;height:').concat(n.toPx(), 'px;')
            }),
            that.frontContext || (that.frontContext = uni.createCanvasContext('front', that)),
            that.bottomContext || (that.bottomContext = uni.createCanvasContext('bottom', that)),
            that.topContext || (that.topContext = uni.createCanvasContext('top', that)),
            that.globalContext || (that.globalContext = uni.createCanvasContext('k-canvas', that)),
                new s.default(that.bottomContext, e).paint(function () {
                  that.isDisabled = false;
                  that.isDisabled = that.outterDisabled;
                  that.$emit('didShow');
                }),
                that.globalContext.draw(),
                that.frontContext.draw(),
                that.topContext.draw())
            : console.error('You should set width and height correctly for painter, width: '.concat(i, ', height: ').concat(n));
      });
      this.touchedView = {};
    },
    startPaint: function () {
      var that = this;
      this.initScreenK();
      this.downloadImages(this.palette).then(function (e) {
        var i = e.width;
        var n = e.height;
        i && n
            ? ((that.canvasWidthInPx = i.toPx()),
            that.widthPixels && (c(that.screenK, that.widthPixels / that.canvasWidthInPx), (that.canvasWidthInPx = that.widthPixels)),
                (that.canvasHeightInPx = n.toPx()),
                that.setData({
                  photoStyle: 'width:'.concat(that.canvasWidthInPx, 'px;height:').concat(that.canvasHeightInPx, 'px;')
                }),
            that.photoContext || (that.photoContext = uni.createCanvasContext('photo', that)),
                new s.default(that.photoContext, e).paint(function () {
                  that.saveImgToLocal();
                }),
                c(that.screenK, that.scaleRatio))
            : console.error('You should set width and height correctly for painter, width: '.concat(i, ', height: ').concat(n));
      });
    },
    downloadImages: function (t) {
      var that = this;
      return new Promise(function (s, n) {
        var o = 0;
        var c = 0;
        var a = JSON.parse(JSON.stringify(t));
        if (a.background) {
          o++;
          r.download(a.background, that.LRU).then(
              function (t) {
                a.background = t;
                c++;
                if (o === c) {
                  s(a);
                }
              },
              function () {
                c++;
                if (o === c) {
                  s(a);
                }
              }
          );
        }
        if (a.views) {
          var h;
          var d = e(a.views);
          try {
            var l = function () {
              var t = h.value;
              if (t && 'image' === t.type && t.url) {
                o++;
                r.download(t.url, that.LRU).then(
                    function (e) {
                      t.originUrl = t.url;
                      t.url = e;
                      uni.getImageInfo({
                        src: e,
                        success: function (e) {
                          t.sWidth = e.width;
                          t.sHeight = e.height;
                        },
                        fail: function (e) {
                          t.url = '';
                          console.error('getImageInfo '.concat(t.url, ' failed, ').concat(JSON.stringify(e)));
                        },
                        complete: function () {
                          c++;
                          if (o === c) {
                            s(a);
                          }
                        }
                      });
                    },
                    function () {
                      c++;
                      if (o === c) {
                        s(a);
                      }
                    }
                );
              }
            };
            for (d.s(); !(h = d.n()).done;) {
              l();
            }
          } catch (t) {
            console.log('CatchClause', t);
            console.log('CatchClause', t);
            d.e(t);
          } finally {
            d.f();
          }
        }
        if (0 === o) {
          s(a);
        }
      });
    },
    saveImgToLocal: function () {
      var that = this;
      var e = this;
      setTimeout(function () {
        uni.canvasToTempFilePath(
            {
              canvasId: 'photo',
              destWidth: e.canvasWidthInPx,
              destHeight: e.canvasHeightInPx,
              success: function (t) {
                e.getImageInfo(t.tempFilePath);
              },
              fail: function (t) {
                console.error('canvasToTempFilePath failed, '.concat(JSON.stringify(t)));
                e.$emit('imgErr', {
                  detail: {
                    error: t
                  }
                });
              }
            },
            that
        );
      }, 300);
    },
    getImageInfo: function (t) {
      var that = this;
      uni.getImageInfo({
        src: t,
        success: function (i) {
          if (that.paintCount > 5) {
            var s = 'The result is always fault, even we tried '.concat(5, ' times');
            console.error(s);
            return void that.$emit('imgErr', {
              detail: {
                error: s
              }
            });
          }
          Math.abs((i.width * that.canvasHeightInPx - that.canvasWidthInPx * i.height) / (i.height * that.canvasHeightInPx)) < 0.01
              ? that.$emit('imgOK', {
                detail: {
                  path: t
                }
              })
              : that.startPaint();
          that.paintCount++;
        },
        fail: function (t) {
          console.error('getImageInfo failed, '.concat(JSON.stringify(t)));
          that.$emit('imgErr', {
            detail: {
              error: t
            }
          });
        }
      });
    }
  },
  created: function () {
  },
  watch: {
    palette: {
      handler: function (t, e) {
        if (this.isNeedRefresh(t, e)) {
          this.paintCount = 0;
          this.startPaint();
        }
      },

      immediate: true,
      deep: true
    },

    dancePalette: {
      handler: function (t, e) {
        this.isEmpty(t) || this.initDancePalette(t);
      },

      immediate: true,
      deep: true
    },

    action: {
      handler: function (t, e) {
        var that = this;
        if (t && !this.isEmpty(t)) {
          this.doAction(
              t,
              function (t) {
                that.movingCache = t;
              },
              false,
              true
          );
        }
      },

      immediate: true,
      deep: true
    },

    disableAction: {
      handler: function (t) {
        this.outterDisabled = t;
        this.isDisabled = t;
      },

      immediate: true
    },

    clearActionBox: {
      handler: function (t) {
        var that = this;
        if (t && !this.needClear && this.frontContext) {
          setTimeout(function () {
            that.frontContext.draw();
          }, 100);
          this.touchedView = {};
          this.prevFindedIndex = this.findedIndex;
          this.findedIndex = -1;
        }
        this.needClear = t;
      },

      immediate: true
    }
  }
};
</script>
<style>
@import './painter.css';
</style>
